package com.atguigu.gmall.activity.consumer;


import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.redis.CacheHelper;
import com.atguigu.gmall.activity.util.DateUtil;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Date;
import java.util.List;

@Component
public class ActivityConsumer {

    @Autowired
    SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = MqConst.ROUTING_TASK_1
    ))
    public void seckillImportRedis(Message message, Channel channel){

        try {
            //组装条件
            QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status",1);
            queryWrapper.gt("stock_count",0);
            queryWrapper.eq("DATE_FORMAT(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
            List<SeckillGoods> seckillGoods = seckillGoodsMapper.selectList(queryWrapper);
            //放入缓存
            if (!CollectionUtils.isEmpty(seckillGoods)){
                seckillGoods.forEach(seckillGoods1 -> {
                    //判断缓存是否存在
                    Boolean aBoolean = redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_GOODS, seckillGoods1.getSkuId().toString());
                    if (!aBoolean) {
                        redisTemplate.opsForHash().put(RedisConst.SECKILL_GOODS, seckillGoods1.getSkuId().toString(),seckillGoods1);

                        //防止超卖
                        redisTemplate.opsForList().leftPushAll(
                                RedisConst.SECKILL_STOCK_PREFIX+seckillGoods1.getSkuId()
                                ,buildSkuIds(seckillGoods1.getSkuId(),seckillGoods1.getStockCount()));

                        //状态位
                        redisTemplate.convertAndSend("seckillpush",seckillGoods1.getSkuId()+":1");
                    }
                });
            }

            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = MqConst.ROUTING_SECKILL_USER
    ))
    public void seckill(UserRecode userRecode,Message message,Channel channel){

        try {
            //检验状态位
            Object status  = CacheHelper.get(userRecode.getSkuId().toString());
            if (!status.equals("1")){
                return;
            }
            //用户是否来过
            Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(RedisConst.SECKILL_USER + userRecode.getUserId(), "1");
            if (!aBoolean){
                //来过了
                return;
            }
            //redis leftpop
            String pop = (String) redisTemplate.opsForList().leftPop(RedisConst.SECKILL_STOCK_PREFIX + userRecode.getSkuId());
            if (StringUtils.isEmpty(pop)){
                //没有 修改状态位
                redisTemplate.convertAndSend("seckillpush",userRecode.getSkuId()+":0");
                return;
            }
            //抢购到了,并记录在redis
            redisTemplate.opsForValue().set(RedisConst.SECKILL_ORDERS+userRecode.getUserId(),userRecode.getSkuId());

            // 收尾 更新数据库……
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String[] buildSkuIds(Long skuId, Integer stockCount) {

        String[] ids = new String[stockCount];
        for (Integer i = 0; i < stockCount; i++) {
            ids[i] = skuId.toString();
        }
        return ids;
    }
}
